<?php
require_once ('utils' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'simple_html_dom.php');
require_once ('utils' . DIRECTORY_SEPARATOR . 'HHAbstract.php');

set_time_limit(-1);

class HHSGeoCodeDB extends HHAbstract {

	public $proxylist;

	function __construct() {
		parent::__construct();
	}

	function __destruct() {
		parent::__destruct();
	}

	function constructClass() {
		$this -> loadProxyList();
		$this -> handleARGV();

	}

	function handleARGV() {
		global $argv;
		if (!isset($argv) || count($argv) <= 1) {
			$this -> scheduleGeoCodeUpdates();

		}
		else {
			array_shift($argv);
			foreach ($argv as $value) {
				$keyArray = split("=", $value);
				$key = $keyArray[0];
				$keyValue = $keyArray[1];
				switch ($key) {
					case "prop_case" :
						$case = $keyValue;
						if (isset($case)) {
							$this -> geoCodeCase($case, 'prop');
						}
						break;
					case "bid_case" :
						$case = $keyValue;
						if (isset($case)) {
							$this -> geoCodeCase($case, 'bid');
						}
						break;
					default :
						echo("Incorrect argument usage. Please use one of the following:\n");
					case "options" :
						$options = array(
							"options" => "Display the options list",
							"prop_case" => "Update the DB with geo data in the property_list table where the entry case equals this parameter",
							"bid_case" => "Update the DB with geo data in the bid_results table where the entry case equals this parameter"
						);
						$space = 0;
						foreach (array_keys ( $options ) as $opKey) {
							$space = (strlen($opKey) > $space) ? strlen($opKey) : $space;
						}
						$space += 5;
						$spaceString = '';
						for ($i = 0; $i < $space; $i++) {
							$spaceString .= " ";
						}
						$length = 70;
						foreach ($options as $opKey => $opValue) {
							$lineCount = 0;
							$displayArray = array();
							$displayArray[$lineCount] = ("\n$opKey" . substr($spaceString, strlen($opKey)));
							$opValueArray = explode(" ", $opValue);
							foreach ($opValueArray as $opValueWord) {
								if ((strlen($displayArray[$lineCount]) + strlen($opValueWord)) <= $length) {
									$displayArray[$lineCount] .= $opValueWord . " ";
								}
								else {
									$lineCount++;
									$displayArray[$lineCount] .= $spaceString . $opValueWord . " ";
								}
							}
							echo(implode("\n", $displayArray) . "\n");
						}
						break;
				}
			}
		}
	}

	function scheduleGeoCodeUpdates() {
		echo("<hr>Scheduling Geocode Updates | Time: " . date("m-d-y h:i:s A") . "<br>");

		// Get the geocode daily UsageLimit
		$usageLimitQuery = 'Select
		if(abs(to_days(NOW())-to_days(updated_at))>=1,2500,`usage`) AS `usage`
		from geocode_daily_limit order by updated_at desc limit 1;';
		$results = $this -> getDBConnection() -> queryDB($usageLimitQuery);
		$row = $results -> fetch_assoc();
		$usageLimit = max(0,$row['usage']);
		
		// Update the usage of the geocode daily limit table
		$updateUsageQuery = 'Update geocode_daily_limit set `usage`='.$usageLimit.', `updated_at`=NOW()';
		$this -> getDBConnection() -> queryDB($updateUsageQuery);

		$query = 'Select `case` from bid_results WHERE lat is null or lon is null  or lat=0 or lon=0 Order by lat asc, rand() limit ' . $usageLimit;
		$results = $this -> getDBConnection() -> queryDB($query);
		$className = get_class($this);
		$file = $className . ".txt";
		while (($row = $results -> fetch_assoc())) {
			$case = $row["case"];
			$cmd = $className . ".php bid_case=$case";
			$this -> getCommandLineHelper() -> run_in_background($cmd, $file);
			$usageLimit--;
		}

		$query = 'Select `case` from property_list WHERE lat is null or lon is null or lat=0 or lon=0 Order by lat asc, rand() limit ' . $usageLimit;
		$results = $this -> getDBConnection() -> queryDB($query);
		$className = get_class($this);
		$file = $className . ".txt";
		while (($row = $results -> fetch_assoc())) {
			$case = $row["case"];
			$cmd = $className . ".php prop_case=$case";
			$this -> getCommandLineHelper() -> run_in_background($cmd, $file);
			$usageLimit--;
		}
		
		// Re-Create the XML used for the Investment Map
		$this -> getCommandLineHelper() -> run_in_background('HHSInvestmentMap.php updateXML=1', 'HHSInvestmentMap.txt');
		
		
	}

	function geoCodeCase($case, $type = 'prop', $try = 2, $proxy = null) {

		$table = 'property_list';
		if ($type != 'prop') {
			$table = 'bid_results';
		}

		if ($try < 2) {
			//$proxy = $this->get_random_proxy();
		}

		// Update bid_results
		$query = 'Select `case`, address, city, state, zip from ' . $table . ' Where `case` = "' . $case . '"';
		$results = $this -> getDBConnection() -> queryDB($query);
		$geoCodeUsage = 0;
		while (($row = $results -> fetch_assoc())) {
			$address = urlencode($row['address'] . ',' . $row['city'] . ',' . $row['state'] . ',' . $row['zip']);
			$geoCodeURL = sprintf("http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false", $address);
			echo("<a href='$geoCodeURL'>$geoCodeURL</a><br>");
			$geoJson = json_decode($this -> get_web_page($geoCodeURL, $proxy), true);
			$geoCodeUsage++;
			$geoStatus = $geoJson['status'];
			if (strcasecmp('OK', $geoStatus) != 0) {
				sleep(rand(1, 3));
				// Try without the zipcode
				$address = urlencode($row['address'] . ',' . $row['city'] . ',' . $row['state']);
				$geoCodeURL = sprintf("http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false", $address);
				echo("Without Zipcode<a href='$geoCodeURL'>$geoCodeURL</a><br>");
				$geoJson = json_decode($this -> get_web_page($geoCodeURL, $proxy), true);
				$geoCodeUsage++;
				$geoStatus = $geoJson['status'];
				if (strcasecmp('OK', $geoStatus) != 0) {
					sleep(rand(1, 3));
					// Try without city or state
					$address = urlencode($row['address'] . ',' . $row['zip']);
					$geoCodeURL = sprintf("http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false", $address);
					echo("Without City or State<a href='$geoCodeURL'>$geoCodeURL</a><br>");
					$geoJson = json_decode($this -> get_web_page($geoCodeURL, $proxy), true);
					$geoCodeUsage++;
					$geoStatus = $geoJson['status'];
					if (strcasecmp('OK', $geoStatus) != 0) {
						sleep(rand(1, 3));
						// Try without city or zipcode
						$address = urlencode($row['address'] . ',' . $row['state']);
						$geoCodeURL = sprintf("http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false", $address);
						echo("Without City or Zipcode<a href='$geoCodeURL'>$geoCodeURL</a><br>");
						$geoJson = json_decode($this -> get_web_page($geoCodeURL, $proxy), true);
						$geoCodeUsage++;
						$geoStatus = $geoJson['status'];
						if (strcasecmp('OK', $geoStatus) != 0) {
							continue;
						}
					}
				}

			}

			$geoResult = array_shift($geoJson['results']);
			$geometry = $geoResult['geometry'];
			$location = $geometry['location'];
			$lat = $location['lat'];
			$lon = $location['lng'];

			if ($lat + $lon == 0) {
				echo("Error getting lat and long from:<br> ");
				echo("<a href='$geoCodeURL'>$geoCodeURL</a><br>");
				var_dump($geoJson);
				echo('<br><br><br>');
				continue;
				// DO not add when lat and long = 0
			}

			$update = sprintf("Update %s set lat=%f, lon=%f where `case`='%s'", $table, $lat, $lon, $case);
			$this -> getDBConnection() -> queryDB($update);
			echo($case . " updated | Time: " . date("m-d-y h:i:s A") . "<br>");
			$try = -1;
		}

		// Update the usage of the geocode daily limit table
		$updateUsageQuery = 'Update geocode_daily_limit set `usage`=`usage`-'.$geoCodeUsage;
		$this -> getDBConnection() -> queryDB($updateUsageQuery);

		if ($try >= 0) {
			sleep(rand(2, 6));
			$this -> geoCodeCase($case, $type, --$try, $proxy);
		}

	}

	function loadProxyList() {
		$proxyfile = 'utils' . DIRECTORY_SEPARATOR . 'includes' . DIRECTORY_SEPARATOR . 'proxy_list.txt';
		$this -> proxylist = file($proxyfile, FILE_IGNORE_NEW_LINES);
	}

	function get_random_proxy() {
		srand((double)microtime() * 1000000);
		return $this -> proxylist[array_rand($this -> proxylist)];
	}

	function get_web_page($url, $proxy = null) {
		// This example request includes an optional API key which you will need to
		// remove or replace with your own key.
		// Read more about why it's useful to have an API key.
		// The request also includes the userip parameter which provides the end
		// user's IP address. Doing so will help distinguish this legitimate
		// server-side traffic from traffic which doesn't come from an end-user.
		// sendRequest
		// note how referer is set manually
		$options = array(
			CURLOPT_URL => $url,
			CURLOPT_RETURNTRANSFER => true, // return web page
			CURLOPT_FOLLOWLOCATION => true, // follow redirects
			CURLOPT_ENCODING => "", // handle all encodings
			CURLOPT_REFERER => "www.hudhomestore.com", // set referer on redirect
			CURLOPT_CONNECTTIMEOUT => 240, // timeout on connect
			CURLOPT_TIMEOUT => 240, // timeout on response
			CURLOPT_MAXREDIRS => 20,
			CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/4',
			CURLOPT_BUFFERSIZE => (1024 * 1024 * 512)
		);

		if (isset($proxy)) {
			//echo("proxy: ".$proxy."<br>");
			$options[CURLOPT_PROXY] = $proxy;
		}

		$ch = curl_init();
		curl_setopt_array($ch, $options);

		$body = curl_exec($ch);
		curl_close($ch);
		return $body;
	}

}

$obj = new HHSGeoCodeDB();
?>